page.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import { Button } from "@/components/ui/button"
  2. import { Card, CardContent } from "@/components/ui/card"
  3. import { Badge } from "@/components/ui/badge"
  4. import { CalendarIcon, ArrowRightIcon } from "lucide-react"
  5. import Image from "next/image"
  6. import Link from "next/link"
  7. import Navigation from "@/components/navigation"
  8. import Footer from "@/components/footer"
  9. import { ThemeProvider } from "@/components/theme-provider"
  10. import { useTranslations } from "next-intl"
  11. import { Metadata } from "next"
  12. export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }): Promise<Metadata> {
  13. const { locale } = await params
  14. const titles = {
  15. en: "Blog - Aiartools | AI Image Editing Tips & News",
  16. zh: "博客 - Aiartools | AI图像编辑技巧与新闻"
  17. }
  18. const descriptions = {
  19. en: "Discover the latest AI image editing tips, tutorials, and news from Aiartools. Learn how to transform your images with artificial intelligence.",
  20. zh: "探索来自Aiartools的最新AI图像编辑技巧、教程和新闻。学习如何用人工智能变换您的图像。"
  21. }
  22. const title = titles[locale as keyof typeof titles] || titles.en
  23. const description = descriptions[locale as keyof typeof descriptions] || descriptions.en
  24. return {
  25. title,
  26. description,
  27. openGraph: {
  28. title,
  29. description,
  30. url: `https://aiartools.com/${locale}/blog`,
  31. siteName: "Aiartools",
  32. locale: locale === 'zh' ? 'zh_CN' : 'en_US',
  33. type: 'website',
  34. },
  35. twitter: {
  36. card: 'summary',
  37. title,
  38. description,
  39. },
  40. alternates: {
  41. canonical: `https://aiartools.com/${locale}/blog`,
  42. languages: {
  43. 'en': 'https://aiartools.com/en/blog',
  44. 'zh': 'https://aiartools.com/zh/blog',
  45. },
  46. },
  47. }
  48. }
  49. interface BlogPageProps {
  50. params: Promise<{ locale: string }>
  51. }
  52. export default async function BlogPage({ params }: BlogPageProps) {
  53. const { locale } = await params
  54. return (
  55. <ThemeProvider attribute="class" defaultTheme="light" enableSystem disableTransitionOnChange>
  56. <div className="min-h-screen bg-background">
  57. <Navigation locale={locale} />
  58. <BlogContent locale={locale} />
  59. <Footer locale={locale} />
  60. </div>
  61. </ThemeProvider>
  62. )
  63. }
  64. function BlogContent({ locale }: { locale: string }) {
  65. const t = useTranslations("blog")
  66. // 博客文章配置,按时间顺序排列
  67. const blogPostsConfig = [
  68. {
  69. key: "contact",
  70. link: `/${locale}/blog/contact-us`,
  71. sortDate: "2025-06-01",
  72. image: "/images/Get in Touch with Aiartools Team.png"
  73. },
  74. {
  75. key: "editingGuide",
  76. link: `/${locale}/blog/how-to-edit-images`,
  77. sortDate: "2025-06-01",
  78. image: "/images/How to Edit Images with Aiartools.png"
  79. },
  80. {
  81. key: "introduction",
  82. link: `/${locale}/blog/introducing-aiartools`,
  83. sortDate: "2025-05-31",
  84. image: "/images/Transform Your Images with the Power of AI.png"
  85. },
  86. ]
  87. // 按时间排序(最新的在前)
  88. const sortedPosts = blogPostsConfig.sort((a, b) =>
  89. new Date(b.sortDate).getTime() - new Date(a.sortDate).getTime()
  90. )
  91. return (
  92. <div className="pt-20">
  93. <div className="container mx-auto px-4 sm:px-6 lg:px-8 py-12">
  94. <div className="text-center mb-16">
  95. <h1 className="text-4xl font-bold mb-4">{t("title")}</h1>
  96. <p className="text-xl text-muted-foreground max-w-3xl mx-auto">{t("subtitle")}</p>
  97. </div>
  98. {/* All Posts */}
  99. <div className="mb-8">
  100. <h2 className="text-2xl font-semibold mb-6">{t("allPosts")}</h2>
  101. <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
  102. {sortedPosts.map((postConfig, index) => (
  103. <Card key={index} className="group hover:shadow-lg transition-all duration-300 overflow-hidden bg-background/60 backdrop-blur-sm border-0">
  104. <Link href={postConfig.link}>
  105. <div className="relative overflow-hidden">
  106. <Image
  107. src={postConfig.image}
  108. alt={t(`posts.${postConfig.key}.title`)}
  109. width={300}
  110. height={200}
  111. className="w-full h-48 object-cover group-hover:scale-105 transition-transform duration-300"
  112. />
  113. <div className="absolute top-4 left-4">
  114. <Badge variant="secondary" className="bg-background/80 backdrop-blur-sm">
  115. {t(`posts.${postConfig.key}.category`)}
  116. </Badge>
  117. </div>
  118. </div>
  119. </Link>
  120. <CardContent className="p-6">
  121. <div className="flex items-center text-sm text-muted-foreground mb-3">
  122. <CalendarIcon className="w-4 h-4 mr-2" />
  123. {t(`posts.${postConfig.key}.date`)}
  124. </div>
  125. <Link href={postConfig.link}>
  126. <h3 className="text-xl font-semibold mb-3 group-hover:text-primary transition-colors cursor-pointer">
  127. {t(`posts.${postConfig.key}.title`)}
  128. </h3>
  129. </Link>
  130. <p className="text-muted-foreground leading-relaxed mb-4">
  131. {t(`posts.${postConfig.key}.excerpt`)}
  132. </p>
  133. <Link href={postConfig.link}>
  134. <Button variant="ghost" className="p-0 h-auto font-semibold text-primary hover:text-primary/80">
  135. {t("readMore")}
  136. <ArrowRightIcon className="w-4 h-4 ml-2" />
  137. </Button>
  138. </Link>
  139. </CardContent>
  140. </Card>
  141. ))}
  142. </div>
  143. </div>
  144. </div>
  145. </div>
  146. )
  147. }